import socket


if __name__ == '__main__':
    # 1.创建服务端套接字对象
    tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 设置端口复用
    tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
    # 2. 绑定IP地址和端口号
    # tcp_server_socket.bind(("172.16.62.136", 8888))
    # 如果bind中的参数第一个ip地址元素设置为"",默认为本机ip地址
    tcp_server_socket.bind(("", 8888))
    # 3.设置监听 128:代表服务端等待排队连接的最大数量
    tcp_server_socket.listen(128)
    # 4.等待接受客户端的连接请求 accept阻塞等待 返回一个用以和客户端通socket,客户端的地址
    conn_socket, ip_port = tcp_server_socket.accept()
    print("客户端地址:", ip_port)
    # 5.接收数据
    recv_data = conn_socket.recv(1024)
    print("接收到的数据:", recv_data.decode())
    # 6.发送数据
    conn_socket.send("客户端你的数据我收到了".encode())
    # 7.关闭套接字
    conn_socket.close()
    tcp_server_socket.close()

"""
小结：
TCP⽹络应⽤程序的注意点介绍：
1. 当 TCP 客户端程序想要和 TCP 服务端程序进⾏通信的时候必须要先
建⽴连接
2. TCP 客户端程序⼀般不需要绑定端⼝号，因为客户端是主动发起建
⽴连接的。
3. TCP 服务端程序必须绑定端⼝号，否则客户端找不到这个 TCP 服务
端程序。
4. listen 后的套接字是被动套接字，只负责接收新的客户端的连接请
求，不能收发消息。
5. 当 TCP 客户端程序和 TCP 服务端程序连接成功后， TCP 服务器端
程序会产⽣⼀个新的套接字，收发客户端消息使⽤该套接字。
6. 关闭 accept 返回的套接字意味着和这个客户端已经通信完毕。
7. 关闭 listen 后的套接字意味着服务端的套接字关闭了，会导致新的客
户端不能连接服务端，但是之前已经接成功的客户端还能正常通信。
8. 当客户端的套接字调⽤ close 后，服务器端的 recv 会解阻塞，返回
的数据⻓度为0，服务端可以通过返回数据的⻓度来判断客户端是否
已经下线，反之服务端关闭套接字，客户端的 recv 也会解阻塞，返
回的数据⻓度也为0。
"""